// #include"Log.hpp"
#include<queue>
#include<vector>
#include<iostream>
#include<mutex>
#include<pthread.h>
using namespace std;

const int task_cap = 5;
const int thread_cap = 3;

template<class T>
class ThreadPool
{
public:
  static ThreadPool<T>* GetInstance()
  {
    static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
    if(inst == nullptr)
    {
      pthread_mutex_lock(&lock);
      if(inst == nullptr)
      {
        //LOG(NOMAL,"单例对象创建成功");
        inst = new ThreadPool<T>();
        //LOG(NOMAL,"线程池初始化成功");
        inst->InitThreadPool();
      }
      pthread_mutex_unlock(&lock);
    }
    return inst;
  }

  ThreadPool(int th_cap = thread_cap,int ta_cap = task_cap) 
    :_thread_cap(th_cap),_task_cap(ta_cap),_exit_flag(false)
  {
    pthread_mutex_init(&_mtx,nullptr);
    pthread_cond_init(&_pro,nullptr);
    pthread_cond_init(&_com,nullptr);
  }

  ~ThreadPool()
  {
    pthread_mutex_destroy(&_mtx);
    pthread_cond_destroy(&_pro);
    pthread_cond_destroy(&_com);
  }
  ThreadPool(const ThreadPool<T>&) = delete;
  ThreadPool<T>& operator=(const ThreadPool<T>&) = delete;
public:
  void push(const T& task)
  {
    pthread_mutex_lock(&_mtx);
    if(_exit_flag)
    {
      pthread_mutex_unlock(&_mtx);
      cout <<"push err" << endl;
      return ;
    }
    while(_task_queue.size() >= _task_cap)
    {
      //LOG(NOMAL,"任务队列数量超过限制");
      pthread_cond_wait(&_pro,&_mtx); 
    }
    _task_queue.push(task);
    pthread_mutex_unlock(&_mtx);
    pthread_cond_signal(&_com);
  }
  void pop(T* task)
  {
    *task = _task_queue.front();
    _task_queue.pop();
  }

  static void* Routine(void* arg)
  {
    pthread_detach(pthread_self());
    ThreadPool<T>* tp = static_cast<ThreadPool<T>*>(arg);
    while(1)
    {
      pthread_mutex_lock(&tp->_mtx);
      while(tp->empty())
      {
        if(tp->_exit_flag)
        {
          tp->_thread_cap--;
          pthread_mutex_unlock(&tp->_mtx);
          cout << pthread_self()  <<"exit" << endl;
          pthread_exit(nullptr);
        }
        pthread_cond_wait(&tp->_com,&tp->_mtx);
      }
      T task;
      tp->pop(&task);
      pthread_mutex_unlock(&tp->_mtx);
      pthread_cond_signal(&tp->_pro);
      
      task();
    }
  }
  bool empty()
  {
    return _task_queue.empty();
  }
  int InitThreadPool()
  {
    int exit_thread = 0;
    for(int i = 0;i<_thread_cap;i++)
    {
      pthread_t tid;
      pthread_create(&tid,nullptr,Routine,(void*)this);
      if(tid < 0) exit_thread++;
    }
    _thread_cap -= exit_thread;
    return _thread_cap;
  }
  void ExitThread()
  {
    _exit_flag = true;
    while(_thread_cap > 0)
    {
      pthread_cond_signal(&_com);
    }
  }
private:
  queue<T> _task_queue;
  pthread_mutex_t _mtx;
  pthread_cond_t _pro;
  pthread_cond_t _com;
  int _thread_cap;
  bool _exit_flag;
  int _task_cap;
  static ThreadPool<T>* inst;
};
template<class T>
ThreadPool<T>* ThreadPool<T>::inst = nullptr;
